"""
认证控制器
处理用户登录、令牌刷新和认证验证相关的HTTP请求
"""
from fastapi import APIRouter, Body, Request

from apps.auth.schemas.auth_schema import RefreshRequest, AuthRequest, LoginResponse, TokenData
from pkg.common.utils.response.response import ApiResponse
from pkg.common.constants.response import ResponseCode
from pkg.common.utils.token.jwt import create_access_token, create_refresh_token, refresh_access_token, verify_token
from pkg.common.constants.auth import TokenType
from apps.auth.services.user_service import UserService
from apps.auth.schemas.user_schema import UserResponse
from pkg.logger import get_logger
logger = get_logger()

# 定义认证路由
router = APIRouter(tags=["认证"])


@router.post("/login", summary="用户登录", response_model=LoginResponse)
async def login(request: Request):
    """
    用户登录接口
    
    支持两种方式传参：
    1. Form表单格式：
       - username: 用户名
       - password: 密码
       
    2. JSON格式：
    ```json
    {
        "username": "用户名",
        "password": "密码"
    }
    ```
    """
    # 获取请求内容类型
    content_type = request.headers.get("content-type", "").lower()

    # 获取用户名和密码
    try:
        if "application/json" in content_type:
            # JSON 数据
            body = await request.json()
            username = body.get("username")
            password = body.get("password")
        else:
            # Form 表单数据
            form = await request.form()
            username = form.get("username")
            password = form.get("password")
    except Exception:
        logger.error("获取用户名和密码失败")
        return ApiResponse.error(
            code=ResponseCode.BAD_REQUEST,
            msg="获取用户名和密码失败"
        )

    # 验证用户凭据
    user, error_msg, error_code = await UserService.authenticate_user(username, password)
    if not user:
        # 根据不同的错误类型返回相应的错误信息
        return ApiResponse.error(
            code=error_code,
            msg=error_msg
        )

    # 创建访问令牌和刷新令牌
    access_token = create_access_token(subject=user.id)
    refresh_token = create_refresh_token(subject=user.id)

    # 更新用户的最后登录时间
    await UserService.update_last_login(user.id)

    # token_data = TokenData(
    #     access_token=access_token,
    #     refresh_token=refresh_token,
    #     token_type="bearer"
    # )
    # 直接返回 token 不包裹 ApiResponse
    # return token_data

    # 返回令牌
    # return ApiResponse[TokenData].success(
    #     code=ResponseCode.SUCCESS,
    #     msg="登录成功",
    #     data=token_data
    # )
    return LoginResponse(
        code=ResponseCode.SUCCESS,
        msg="登录成功",
        data={"uid": user.id},
        access_token=access_token,
        refresh_token=refresh_token,
        token_type="bearer"
    )


@router.post("/refresh", summary="刷新访问令牌")
async def refresh(refresh_req: RefreshRequest = Body(...)):
    """
    刷新访问令牌
    
    使用刷新令牌获取新的访问令牌
    
    Args:
        refresh_req: 包含刷新令牌的请求体
        
    Returns:
        包含新访问令牌的响应
    """
    try:
        # 使用刷新令牌生成新的访问令牌
        token_data = refresh_access_token(refresh_req.refresh_token)

        # 从刷新令牌中获取用户ID
        user_id = verify_token(refresh_req.refresh_token, TokenType.REFRESH)

        # 获取用户信息
        # user = await UserService.get_user_by_id(int(user_id))

        # 返回新的访问令牌和用户信息
        return ApiResponse.success(
            msg="令牌刷新成功",
            data={
                "access_token": token_data["access_token"],
                "token_type": token_data["token_type"],
                # "user": UserResponse.model_validate(user)
            }
        )

    except Exception as e:
        return ApiResponse.error(
            code=ResponseCode.UNAUTHORIZED,
            msg=f"令牌刷新失败: {str(e)}"
        )


@router.post("/verify", summary="验证令牌")
async def verify_auth(auth_req: AuthRequest = Body(...)):
    """
    验证认证令牌
    
    验证访问令牌或刷新令牌是否有效
    
    Args:
        auth_req: 包含令牌的请求体
        
    Returns:
        如果令牌有效，则返回用户信息
    """
    try:
        # 尝试验证访问令牌
        try:
            user_id = verify_token(auth_req.token, TokenType.ACCESS)
        except Exception:
            # 如果访问令牌无效，则尝试验证刷新令牌
            user_id = verify_token(auth_req.token, TokenType.REFRESH)

        # 获取用户信息
        user = await UserService.get_user_by_id(int(user_id))

        # 返回认证成功响应
        return ApiResponse.success(
            msg="认证成功",
            data={
                "user": UserResponse.model_validate(user)
            }
        )

    except Exception as e:
        return ApiResponse.error(
            code=ResponseCode.UNAUTHORIZED,
            msg=f"认证失败: {str(e)}"
        )
